#pragma once

#include "Thread.hpp"
#include "LockGuard.hpp"
#include <vector>
#include <queue>
#include <mutex>
#include <pthread.h>
#include <unistd.h>

using namespace ThreadNs;

const int gnum = 3;

template <class T>
class ThreadPool;

template <class T>
struct ThreadData
{
    ThreadPool<T> *threadpool;
    std::string name;
    ThreadData(ThreadPool<T> *tp, const std::string &n) : threadpool(tp), name(n) {}
};

template <class T>
class ThreadPool
{
private:
    //禁掉拷贝构造和赋值重载，实现单例模式
    ThreadPool(const ThreadPool &) = delete;
    void operator=(const ThreadPool &) = delete;

    ThreadPool(const int &num = gnum) : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for (int i = 0; i < _num; i++)
        {
            _threads.push_back(new Thread());//初始化线程对象，但是并未调用pthread_create创建出线程
        }
    }
    static void *handlerTask(void *args)
    {
        ThreadData<T> *td = (ThreadData<T> *)args;
        while (true)
        {
            T t;
            {
                LockGuard lockguard(&td->threadpool->_mutex);
                while (td->threadpool->isQueueEmpty())
                {
                    td->threadpool->threadWait();
                }
                t = td->threadpool->pop(); // pop的本质，是将任务从公共队列中，拿到当前线程自己独立的栈中
            }
            std::cout << td->name << " 获取了一个任务： " << t.toTaskString() << " 并处理完成，结果是：" << t() << std::endl;
        }
        delete td;
        return nullptr;
    }
public:
    void lockQueue() { pthread_mutex_lock(&_mutex); }
    void unlockQueue() { pthread_mutex_unlock(&_mutex); }
    bool isQueueEmpty() { return _task_queue.empty(); }
    void threadWait() { pthread_cond_wait(&_cond, &_mutex); }
    T pop()
    {
        T t = _task_queue.front();
        _task_queue.pop();
        return t;
    }
    void push(const T &in)
    {
        LockGuard lockguard(&_mutex);
        _task_queue.push(in);
        pthread_cond_signal(&_cond);
    }
    void run()
    {
        for (const auto &t : _threads)
        {
            ThreadData<T> *td = new ThreadData<T>(this, t->threadname());
            t->start(handlerTask, td);//线程真正的跑起来了
            std::cout << t->threadname() << " start ..." << std::endl;
        }
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (const auto &t : _threads)
            delete t;//释放对象地址，防止内存泄露
    }
    static ThreadPool<T> *getInstance()//获取单例对象的地址，通过该地址来访问对象内部函数
    {
        if (nullptr == tp)//先判断后加锁，效率更高
        {
            LockGuard lockguard(&_singleLock);
            if (nullptr == tp)
            {
                tp = new ThreadPool<T>();
            }
        }
        return tp;
    }
private:
    int _num;
    std::vector<Thread *> _threads;
    //任务队列+锁+条件变量，保证对任务队列的操作是线程安全的，同时pthread和cthread实现同步操作
    std::queue<T> _task_queue;q
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;//线程在没有任务可执行的时候，便在cond条件变量下进行等待，有任务的时候再将其唤醒

    //两个静态成员变量，实现出单例模式
    volatile static ThreadPool<T> *tp;//保持内存的可见性
    static pthread_mutex_t _singleLock;//用原生线程库的锁，单例对象锁，保证获取单例对象的过程是线程安全的
};

template <class T>
volatile ThreadPool<T> *ThreadPool<T>::tp = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::_singleLock;
